//package com.turing.post.util;

//import com.turing.post.util.Dependency;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Vector;
import java.io.*;

import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.types.FileSet;

public class Depends extends Task {

	/**
	 * 对象流MAGIC
	 */
	private final static int DEPENDS_MAGIC = 0x504F5354;

	/**
	 * 建立依赖关系 -- 编译J2EE SHARED LIBRARY时使用
	 */
	private final static String DEPENDS_CMD_MAINTENCE = "Maintenance";

	/**
	 * 查看依赖关系 -- 检查依赖关系
	 */
	private final static String DEPENDS_CMD_SHOW = "Show";

	/**
	 * 遍历依赖关系 -- 编译J2EE APPLICATION时使用
	 */
	private final static String DEPENDS_CMD_RESOLVE = "Resolve";

	private final Vector<FileSet> filesets = new Vector<FileSet>();

	/**
	 * 本次命令
	 */
	private String dependsCmd;

	/**
	 * 本库包名称
	 */
	private String libraryName;

	/**
	 * 序列化类名-依赖类名集合\类名-库名的文件名
	 */
	private String serialFileName;

	/**
	 * 类的前缀名,如com.turing.post等
	 */
	private String clsPrefixName;

	private String thirdParty;

	/**
	 * 查看指定类的依赖关系,如为null或长度为0,则查看整个列表
	 */
	private String showClsDepends;

	/**
	 * weblogicApplicationXML文件名
	 */
	private String weblogicApplicationXML;

	/**
	 * KEY - 类名 VALUE - 该类名依赖的所有外部对象
	 */
	private HashMap<String, HashSet<String>> clsDepends = new HashMap<String, HashSet<String>>();

	/**
	 * KEY - 类名 VALUE - 该类名所属的共享库名
	 */
	private HashMap<String, String> clsLibs = new HashMap<String, String>();

	/**
	 * KEY - 类名, 实体类集合
	 */
	private HashSet<String> entityClassSet = new HashSet<String>();

	/**
	 * KEY - 类名 VALUE - true(Stateless, Stateful) false(MessageDriven) Bean,
	 * EJB类集合
	 */
	private HashMap<String, Boolean> ejbClassSet = new HashMap<String, Boolean>();

	/**
	 * 用于保存待Ehancer的实体类列表的XML文件名
	 */
	private String enhancerXml;

	public void setEnhancerXml(String enhancerXml) {
		this.enhancerXml = enhancerXml;
	}

	/**
	 * 用于生成application.xml的文件名
	 */
	private String applicationXml;

	/**
	 * 用于生成persistence.xml的文件名
	 */
	private String persistenceXml;

	/**
	 * 用于产生weblogic-ejb-jar.xml的部署文件名
	 */
	private String weblogicEjbJarXml;

	/**
	 * 用于生成persistence.xml中的数据源
	 */
	private String datasourceName;

	/**
	 * 用于生成application.xml中的module名
	 */
	private String jarFile;

	/**
	 * 用于通知ant如何进行打包
	 */
	private String javaModule;

	public void setJavaModule(String javaModule) {
		this.javaModule = javaModule;
	}

	public void setJarFile(String jarFile) {
		this.jarFile = jarFile;
	}

	public void setDatasourceName(String datasourceName) {
		this.datasourceName = datasourceName;
	}

	public void setWeblogicEjbJarXml(String weblogicEjbJarXml) {
		this.weblogicEjbJarXml = weblogicEjbJarXml;
	}

	public void setPersistenceXml(String persistenceXml) {
		this.persistenceXml = persistenceXml;
	}

	public void setApplicationXml(String applicationXml) {
		this.applicationXml = applicationXml;
	}

	public void setShowClsDepends(String showClsDepends) {
		this.showClsDepends = showClsDepends;
	}

	public void setDependsCmd(String dependsCmd) {
		this.dependsCmd = dependsCmd;
	}

	public void setLibraryName(String libraryName) {
		this.libraryName = libraryName;
	}

	public void setSerialFileName(String serialFileName) {
		this.serialFileName = serialFileName;
	}

	public void setClsPrefixName(String clsPrefixName) {
		this.clsPrefixName = clsPrefixName;
	}

	public void setWeblogicApplicationXML(String weblogicApplicationXML) {
		this.weblogicApplicationXML = weblogicApplicationXML;
	}

	public void setThirdParty(String thirdParty) {
		this.thirdParty = thirdParty;
	}

	/**
	 * 增加文件集到filesets中,该方法是ant的接口要求
	 * 
	 * @param fileset
	 */
	public void addFileset(FileSet fileset) {
		filesets.add(fileset);
	}

	/**
	 * 遍历输出
	 * 
	 * @param FileList
	 */
	public static void dumpFiles(HashSet<String> FileList) {
		for (String files : FileList)
			System.out.println(files);
	}

	/**
	 * 将allclass中的每一个class文件，转换为真正的全类名
	 * 
	 * @param allclass
	 * @param pkgprefix
	 */
	public static HashSet<String> resolveAllClass(HashSet<String> allclass,
			String pkgprefix) {
		HashSet<String> cls = new HashSet<String>();

		for (String name : allclass) {
			// 取后面的名字
			String pkgclsname = name.substring(pkgprefix.length());

			// 确保起始位置不含路径分隔符
			while (pkgclsname.startsWith(File.separator))
				pkgclsname = pkgclsname.substring(1);

			// 从.class处截断
			pkgclsname = pkgclsname.substring(0, pkgclsname.length() - 6);

			// System.out.println(pkgclsname);

			// 替换路径分隔符为.
			while (pkgclsname.contains(File.separator))
				pkgclsname = pkgclsname.replace(File.separator, ".");

			// System.out.println(pkgclsname);

			// 加到返回列表
			cls.add(pkgclsname);
		}

		return cls;
	}

	/**
	 * 分析某class文件中所有依赖的类名,以指定类名开头
	 * 
	 * @param clsfilename
	 *            类文件名
	 * @param clsname
	 *            类名
	 * @param pkgprefix
	 *            关心的前缀名
	 * @throws IOException
	 */
	public static HashSet<String> analyze(String clsfilename, String clsname,
			String pkgprefix) throws IOException {
		HashMap<Integer, String> allutf8 = new HashMap<Integer, String>();
		HashSet<Integer> allcls = new HashSet<Integer>();
		HashSet<String> dependsClass = new HashSet<String>();

		// 文件输入流
		DataInputStream input = new DataInputStream(new BufferedInputStream(
				new FileInputStream(clsfilename)));

		// read magic number:
		int magic = input.readInt();
		if (magic != 0xCAFEBABE)
			throw new RuntimeException("Invalid magic number!");

		// read minor version and major version:
		/* short minor_ver = */input.readShort();
		/* short major_ver = */input.readShort();
		// System.out.println("Version = " + major_ver + "." + minor_ver);

		// read constant pool:
		short const_pool_count = input.readShort();
		// System.out.println("constant pool size = " + const_pool_count);

		// read each constant:
		for (int i = 1; i < const_pool_count; i++)
			analyzeConstant(allutf8, allcls, input, i);

		// System.out.println("all classes list ...");
		for (Integer clsidx : allcls) {
			if (allutf8.containsKey(clsidx)) {
				// System.out.println(allutf8.get(clsidx));
				StringBuffer stringbuffer = new StringBuffer(allutf8
						.get(clsidx).replace('/', '.'));
				String clsname1 = stringbuffer.toString();
				// 不关心自己
				if (clsname1.equals(clsname))
					continue;
				// 跳过内部嵌套类
				if (clsname1.indexOf("$") >= 0)
					continue;
				// 只关心特定前缀的类名
				if (pkgprefix == null || clsname1.startsWith(pkgprefix))
					dependsClass.add(clsname1);
			} else
				throw new RuntimeException(clsidx + " NOT FOUND!!!");
		}

		return dependsClass;
	}

	public static void analyzeConstant(HashMap<Integer, String> allutf8,
			HashSet<Integer> allcls, DataInputStream input, int index)
			throws IOException {
		byte flag = input.readByte();
		// for read:
		// byte n8;
		short n16;
		// int n32;
		// long n64;
		// float f;
		// double d;
		byte[] buffer;

		// System.out.println("\nconst index = " + index + ", flag = "
		// + (int) flag);
		switch (flag) {
		case 1: // utf-8 string
			// System.out.println(" const type = Utf8");
			n16 = input.readShort();
			// System.out.println("     length = " + n16);
			buffer = new byte[n16];
			input.readFully(buffer);
			// System.out.println("      value = " + new String(buffer));
			allutf8.put(new Integer(index), new String(buffer));
			break;
		case 3: // integer
			// System.out.println(" const type = Integer");
			/* n32 = */
			input.readInt();
			// System.out.println("      value = " + n32);
			break;
		case 4: // float
			// System.out.println(" const type = Float");
			/* f = */
			input.readFloat();
			// System.out.println("      value = " + f);
			break;
		case 5: // long
			// System.out.println(" const type = Long");
			/* n64 = */
			input.readLong();
			// System.out.println("      value = " + n64);
			break;
		case 6: // double
			// System.out.println(" const type = Double");
			/* d = */
			input.readDouble();
			// System.out.println("      value = " + d);
			break;
		case 7: // class or interface reference
			// System.out.println(" const type = Class");
			n16 = input.readShort();
			allcls.add(new Integer(n16));
			// System.out.println("      index = " + n16
			// + " (where to find the class name)");
			break;
		case 8: // string
			// System.out.println(" const type = String");
			/* n16 = */
			input.readShort();
			// System.out.println("      index = " + n16);
			break;
		case 9: // field reference
			// System.out.println(" const type = Fieldref");
			/* n16 = */
			input.readShort();
			// System.out.println("class index = " + n16
			// + " (where to find the class)");
			/* n16 = */
			input.readShort();
			// System.out.println("nameAndType = " + n16
			// + " (where to find the NameAndType)");
			break;
		case 10: // method reference
			// System.out.println(" const type = Methodref");
			/* n16 = */
			input.readShort();
			// System.out.println("class index = " + n16
			// + " (where to find the class)");
			/* n16 = */
			input.readShort();
			// System.out.println("nameAndType = " + n16
			// + " (where to find the NameAndType)");
			break;
		case 11: // interface method reference
			// System.out.println(" const type = InterfaceMethodref");
			/* n16 = */
			input.readShort();
			// System.out.println("class index = " + n16
			// + " (where to find the interface)");
			/* n16 = */
			input.readShort();
			// System.out.println("nameAndType = " + n16
			// + " (where to find the NameAndType)");
			break;
		case 12: // name and type reference
			// System.out.println(" const type = NameAndType");
			/* n16 = */
			input.readShort();
			// System.out.println(" name index = " + n16
			// + " (where to find the name)");
			/* n16 = */
			input.readShort();
			// System.out.println(" descripter = " + n16
			// + " (where to find the descriptor)");
			break;
		default:
			throw new RuntimeException("Invalid constant pool flag: " + flag);
		}
	}

	public void refreshClassMappingLibrary(String libraryName) {
		for (Map.Entry<String, String> entry : clsLibs.entrySet()) {
			if (entry.getValue().equals(libraryName)) {
				clsLibs.remove(entry.getValue());
			}
		}
	}

	/**
	 * 输出所有的依赖关系
	 */
	private void dumpAllDepends() {
		System.out.println("CLASS IN LIBRARY LIST ENTRYS: " + clsLibs.size());
		for (Map.Entry<String, String> entry : clsLibs.entrySet())
			System.out.println(entry.getValue() + " : " + entry.getKey());

		System.out.println();
		System.out.println("CLASS DEPENDS EXTERN CLASS LIST ENTRYS: "
				+ clsDepends.size());
		for (Map.Entry<String, HashSet<String>> entry : clsDepends.entrySet()) {
			System.out.println(entry.getKey() + ":");
			HashSet<String> deps = entry.getValue();
			if (deps == null || deps.size() == 0) {
				System.out.println("\tNO DEPENDS!");
				continue;
			}
			for (String cls : deps)
				System.out.println("\t" + cls);
		}
	}

	/**
	 * 遍历查找指定类的外部依赖关系
	 * 
	 * @param cls
	 * @param deplibs
	 * @param deppri
	 *            按次序的引用关系
	 * @param ignlibs
	 * @param igncls
	 * @param clsList
	 */
	private void getDependsLibraryByClassName(String cls,
			HashSet<String> deplibs, Vector<String> deppri,
			HashSet<String> ignlibs, HashSet<String> igncls,
			HashSet<String> clsList) {
		HashSet<String> extcls = null;

		if (cls.indexOf("$") > 0)
			return;

		System.out.println("cls:" + cls);

		// step 1:确定cls的外部依赖类
		// 如果已经被处理过了,则直接返回
		if (igncls.contains(cls))
			return;

		extcls = clsDepends.get(cls);

		// step 2:遍历处理该类的直接依赖类
		if (extcls != null) {
			for (String excls : extcls) {
				// 如果已经被处理过了,则继续下一个
				if (igncls.contains(excls))
					continue;

				// 递归处理
				getDependsLibraryByClassName(excls, deplibs, deppri, ignlibs,
						igncls, clsList);

				// 把该类加入到已处理过的列表
				if (!igncls.contains(excls))
					igncls.add(excls);
			}
		}

		String libs = clsLibs.get(cls);
		if (libs == null) {
			// 当前列表已经包含
			if (clsList.contains(cls))
				return;

			throw new BuildException("UNRESOLVED: " + cls);
		}
		// 如果在忽略库列表则不处理之
		if (ignlibs.contains(libs))
			return;

		// 如果已经在deplibs则不处理之
		if (deplibs.contains(libs))
			return;

		// 增加到依赖库中
		deplibs.add(libs);
		deppri.add(libs);

		// 忽略列表中亦增加之
		ignlibs.add(libs);
	}

	/**
	 * 查找指定的集合中所有类,所直接或间接依赖的类
	 * 
	 * @param clsList
	 * @return Vector<String> 依赖关系的优先级顺序
	 */
	private Vector<String> getDependsLibrary(HashSet<String> clsList) {
		// 最终依赖的外部库列表
		HashSet<String> deplibs = new HashSet<String>();
		Vector<String> deppri = new Vector<String>();

		// 忽略的库列表,也就是这些类本身所在的库应该位于ignlibs,将不进入deplibs
		HashSet<String> ignlibs = new HashSet<String>();

		// 忽略的类列表,也就是这些类已经处理过了
		HashSet<String> igncls = new HashSet<String>();

		// step 1:将clsList对应的Lib加入到ignlibs
		for (String cls : clsList) {
			String lib = clsLibs.get(cls);
			// 不包含的情况下进入ignlibs
			if (lib != null && !ignlibs.contains(lib))
				ignlibs.add(lib);
		}

		// step 2:针对clsList中的每一个类,查找其直接或间接依赖的类
		for (String cls : clsList) {
			getDependsLibraryByClassName(cls, deplibs, deppri, ignlibs, igncls,
					clsList);
			// 把该类置入已处理过的列表
			if (!igncls.contains(cls))
				igncls.add(cls);
		}

		return deppri;
	}

	/**
	 * 显示依赖关系
	 * 
	 * @param deplibs
	 */
	private void ShowDepends(Vector<String> deplibs) {
		System.out.println("\tDEPENDS LIB LIST(" + deplibs.size() + "):");
		for (String lib : deplibs)
			System.out.println("\t" + lib);
	}

	/**
	 * 查看依赖关系
	 * 
	 * @throws BuildException
	 */
	private void Show() throws BuildException {
		if (showClsDepends == null || showClsDepends.length() == 0
				|| showClsDepends.startsWith("${")) {
			dumpAllDepends();
			return;
		}
		HashSet<String> clslist = new HashSet<String>();
		clslist.add(showClsDepends);

		Vector<String> deplibs = getDependsLibrary(clslist);

		System.out.println("[CLASS] " + showClsDepends);
		ShowDepends(deplibs);
	}

	/**
	 * 根据deplibs产生weblogic-application.xml
	 * 
	 * @param waxml
	 * @param deplibs
	 */
	private void genWeblogicApplicationXML(String waxml, Vector<String> deplibs1) {
		File write = null;
		BufferedWriter bw = null;
		Vector<String> deplibs = deplibs1;
		try {

			if (thirdParty != null) {
				String[] str = thirdParty.split(",");
				for (int i = 0; i < str.length; i++) {
					String s = str[i].trim();
					if (s.length() > 0 && s.startsWith("LIB."))
						deplibs.add(s);
				}
			}

			write = new File(waxml);

			bw = new BufferedWriter(new FileWriter(write));

			bw.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
			bw.newLine();

			bw
					.write("\t<wls:weblogic-application xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:wls=\"http://www.bea.com/ns/weblogic/weblogic-application\" xsi:schemaLocation=\"http://www.bea.com/ns/weblogic/weblogic-application http://www.bea.com/ns/weblogic/weblogic-application.xsd http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/j2ee_1_4.xsd\">");
			bw.newLine();

			for (String lib : deplibs) {
				bw.write("\t\t<wls:library-ref>");
				bw.newLine();

				bw.write("\t\t\t<wls:library-name>");
				bw.write(lib);
				bw.write("</wls:library-name>");
				bw.newLine();

				bw
						.write("\t\t\t<wls:specification-version>1.0</wls:specification-version>");
				bw.newLine();

				bw
						.write("\t\t\t<wls:implementation-version>1.0</wls:implementation-version>");
				bw.newLine();

				bw.write("\t\t\t<wls:exact-match>false</wls:exact-match>");
				bw.newLine();

				bw.write("\t\t</wls:library-ref>");
				bw.newLine();
			}

			bw.write("\t</wls:weblogic-application>");
			bw.newLine();

			bw.close();
		} catch (Exception ex_) {
			throw new BuildException(ex_.toString());
		} finally {
			write = null;
			bw = null;
		}
	}

	/**
	 * 产生用于Enhancer的实体类列表
	 * 
	 * @param pxml
	 * @param isEjbModule
	 */
	private void generateApplicationXML(String pxml, String jarfilename,
			boolean isEjbModule) {
		File write = null;
		BufferedWriter bw = null;

		try {
			// 仅获取jar的真正文件名,不包含目录
			String jarName = new File(jarfilename).getName();
			String packageName = jarName;

			if (jarName.endsWith(".jar"))
				packageName = jarName.substring(0, jarName.length() - 4);

			write = new File(pxml);

			bw = new BufferedWriter(new FileWriter(write));

			bw.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
			bw.newLine();

			bw
					.write("<application xmlns=\"http://java.sun.com/xml/ns/j2ee\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" version=\"1.4\">");
			bw.newLine();

			bw.write("\t<description>");
			bw.write(packageName);
			bw.write(" Shared Library</description>");
			bw.newLine();

			bw.write("\t<display-name>");
			bw.write(packageName);
			bw.write(" Shared Library</display-name>");
			bw.newLine();

			bw.write("\t<module>");
			bw.newLine();

			if (isEjbModule) {
				bw.write("\t\t<ejb>");
				bw.write(jarName);
				bw.write("</ejb>");
			} else {
				bw.write("\t\t<java>");
				bw.write("APP-INF/lib/");
				bw.write(jarName);
				bw.write("</java>");
			}

			bw.newLine();

			bw.write("\t</module>");
			bw.newLine();

			bw.write("</application>");
			bw.newLine();

			bw.close();
		} catch (Exception ex_) {
			throw new BuildException(ex_.getMessage());
		} finally {
			write = null;
			bw = null;
		}
	}

	/**
	 * 产生weblogic-ejb-jar.xml部署描述符xml文件
	 */
	private void generateWeblogicEjbJarXML() {
		File write = null;
		BufferedWriter bw = null;
		try {
			write = new File(weblogicEjbJarXml);

			bw = new BufferedWriter(new FileWriter(write));
			
			bw.write("<?xml version=\"1.0\"?>");
			bw.newLine();
			
			bw.write("<weblogic-ejb-jar ");
			bw.write("xmlns=\"http://www.bea.com/ns/weblogic/90\" ");
			bw.write("xmlns:j2ee=\"http://java.sun.com/xml/ns/j2ee\" ");
			bw.write("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ");
			bw.write("xsi:schemaLocation=\"http://www.bea.com/ns/weblogic/90 http://www.bea.com/ns/weblogic/90/weblogic-ejb-jar.xsd\">");
			bw.newLine();
			
			for (Map.Entry<String, Boolean> ejbentry : ejbClassSet.entrySet()){
				String ejbclass = ejbentry.getKey();
				if (ejbentry.getValue() == false)
					continue;
				
				String ejbname = ejbclass.substring( 1 + ejbclass.lastIndexOf(".") );
				bw.write("\t<weblogic-enterprise-bean>");
				bw.newLine();
				bw.write("\t\t<ejb-name>" + ejbname + "</ejb-name>");
				bw.newLine();
		        bw.write("\t\t<stateless-session-descriptor>");
		        bw.newLine();
		        bw.write("\t\t\t<pool>");
		        bw.newLine();
		        bw.write("\t\t\t\t<max-beans-in-free-pool>300</max-beans-in-free-pool>");
		        bw.newLine();
		        bw.write("\t\t\t\t<initial-beans-in-free-pool>5</initial-beans-in-free-pool>");
		        bw.newLine();
		        bw.write("\t\t\t</pool>");
		        bw.newLine();
		        bw.write("\t\t</stateless-session-descriptor>");
		        bw.newLine();
		        bw.write("\t\t<transaction-descriptor>");
		        bw.newLine();
		        bw.write("\t\t\t<trans-timeout-seconds>36000</trans-timeout-seconds>");
		        bw.newLine();
		        bw.write("\t\t</transaction-descriptor>");
		        bw.newLine();
		        bw.write("\t\t<enable-call-by-reference>true</enable-call-by-reference>");
		        bw.newLine();
		        bw.write("\t</weblogic-enterprise-bean>");
		        bw.newLine();
			}
			
			bw.write("</weblogic-ejb-jar>");
			bw.newLine();
			
			bw.close();
			
		} catch (Exception ex_) {
			throw new BuildException(ex_.toString());
		} finally {
			write = null;
			bw = null;
		}
	}

	/**
	 * 产生用于Enhancer的实体类列表
	 * 
	 * @param pxml
	 * @param entityClass
	 */
	private void generatePersistenceXML(String pxml, String unitName,
			HashSet<String> entityClass) {
		File write = null;
		BufferedWriter bw = null;
		try {
			write = new File(pxml);

			bw = new BufferedWriter(new FileWriter(write));

			bw.write("<?xml version=\"1.0\"?>");
			bw.newLine();

			bw
					.write("<persistence xmlns=\"http://java.sun.com/xml/ns/persistence\" ");
			bw.newLine();

			bw
					.write("\txmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ");
			bw.newLine();

			bw
					.write("\txsi:schemaLocation=\"http://java.sun.com/xml/ns/persistence ");
			bw.newLine();

			bw
					.write("\thttp://java.sun.com/xml/ns/persistence/persistence_1_0.xsd\" ");
			bw.newLine();

			bw.write("\tversion=\"1.0\">");
			bw.newLine();

			bw.write("\t<persistence-unit name=\"" + unitName
					+ "\" transaction-type=\"JTA\">");
			bw.newLine();

			bw.write("\t\t<jta-data-source>" + unitName + "</jta-data-source>");
			bw.newLine();

			if (entityClass == null) {
				// bw
				// .write("\t\t<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>");
				// bw.newLine();
				bw
						.write("\t\t<exclude-unlisted-classes>true</exclude-unlisted-classes>");
				bw.newLine();
			} else {
				for (String entityclass : entityClass) {
					bw.write("\t\t<class>" + entityclass + "</class>");
					bw.newLine();
				}
			}

			bw.write("\t\t<properties>");
			bw.newLine();

			// bw.write("\t\t\t<property name=\"openjpa.MetaDataFactory\" value=\"jpa\"/>");
			// bw.newLine();
			// bw.write("\t\t\t<property name=\"openjpa.Log\" value=\"SQL=TRACE,DefaultLevel=TRACE,Tool=TRACE,Enhance=TRACE\"/>");
			// bw.write("\t\t\t<property name=\"openjpa.Log\" value=\"SQL=TRACE\"/>");
			// bw.newLine();

			bw.write("\t\t</properties>");
			bw.newLine();

			bw.write("\t</persistence-unit>");
			bw.newLine();

			bw.write("</persistence>");
			bw.newLine();

			bw.close();
		} catch (Exception ex_) {
			throw new BuildException(ex_.toString());
		} finally {
			write = null;
			bw = null;
		}
	}

	/**
	 * 遍历依赖关系
	 * 
	 * @throws BuildException
	 */
	private void Resolve() throws BuildException {
		HashSet<String> currentclslist = new HashSet<String>();

		// 必须指定weblogic-application.xml文件名
		if (weblogicApplicationXML == null
				|| weblogicApplicationXML.length() == 0)
			throw new BuildException("NO weblogic-application.xml FILE NAME!");

		// 确保找到至少一个文件集
		if (filesets.size() == 0)
			throw new BuildException("NO FILESET!");

		for (int i = 0; i < filesets.size(); i++) {
			FileSet fs = filesets.get(i);
			DirectoryScanner ds = fs.getDirectoryScanner();
			String[] files = ds.getIncludedFiles();
			for (int j = 0; j < files.length; j++) {
				// System.out.println(fs.getDir());
				// System.out.println(files[j]);

				String clsname = files[j];
				// 不处理非.class文件
				if (!clsname.endsWith(".class"))
					continue;
				// 不处理文件名中包含$的文件
				if (clsname.indexOf("$") > 0)
					continue;
				// 解析.class类文件
				Dependency dependency = null;
				try {
					System.out.println("BEGIN PARSE:" + fs.getDir()
							+ File.separator + files[j]);
					dependency = Dependency.getDependency(fs.getDir()
							+ File.separator + files[j], clsPrefixName);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					throw new BuildException("ANALYZ class: " + fs.getDir()
							+ File.separator + files[j] + " FAILED!!!");
				}

				// 获取该class文件的全类名
				clsname = dependency.getSelfName();

				// 当前类列表
				currentclslist.add(clsname);

				// 如果是entity
				if (dependency.isEntity()) {
					// 如果有primary key,则亦将其加入之
					/*
					 * if (dependency.hasPrimaryKey()){ if
					 * (!entityClassSet.contains
					 * (dependency.getPrimaryKeyClass()))
					 * entityClassSet.add(dependency.getPrimaryKeyClass()); }
					 */
					if (!entityClassSet.contains(clsname))
						entityClassSet.add(clsname);
				}

				// 如果是ejb
				if (dependency.isEJB() && !ejbClassSet.containsKey(clsname)) {
					ejbClassSet.put(clsname, !dependency.isMessageDrivenEJB());
				}

				// 将类名从依赖表中去除
				if (clsDepends.containsKey(clsname)) {
					clsDepends.remove(clsname);
				}

				// 从类-库依赖表中去除
				if (!clsLibs.containsKey(clsname)) {
					// 不包含该类,直接增加
					clsLibs.put(clsname, libraryName);
				} else if (!clsLibs.get(clsname).equals(libraryName)) {
					// 包含，但指向的库名不对,则先删除后增加
					clsLibs.remove(clsname);
					clsLibs.put(clsname, libraryName);
				}

				// 获取依赖集合
				HashSet<String> depends = dependency.getDependClass();
				if (depends == null || depends.size() == 0)
					depends = null;
				/*
				 * if (depends != null) { System.out.println("current class <" +
				 * clsname + "> depends list:"); dumpFiles(depends); }
				 */
				// 加入到类-依赖集合中
				clsDepends.put(clsname, depends);
			}
		}

		// 产生所有必要的xml
		generateAllXml();

		// 解决依赖关系
		Vector<String> deplibs = getDependsLibrary(currentclslist);

		// 显示依赖关系
		ShowDepends(deplibs);

		// 产生weblogic-application.xml部署文件
		genWeblogicApplicationXML(weblogicApplicationXML, deplibs);
	}

	private boolean isEmptyParam(String antParams) {
		return (antParams == null || antParams.length() == 0 || antParams
				.startsWith("${"));
	}

	private void generateAllXml() {
		// 如果存在实体表,则产生待enhancer.xml
		if (entityClassSet.size() > 0)
			generatePersistenceXML(enhancerXml,
					isEmptyParam(datasourceName) ? "none" : datasourceName,
					entityClassSet);

		// 如果存在,则生成persistence.xml用于部署
		// 仅包中存在EJB类时才需要
		if (ejbClassSet.size() > 0) {
			if (!isEmptyParam(persistenceXml) && !isEmptyParam(datasourceName))
				generatePersistenceXML(persistenceXml, datasourceName, null);
			// 2013.02.03
			generateWeblogicEjbJarXML();
		} else {
			if (!isEmptyParam(javaModule)) {
				try {
					new File(javaModule).createNewFile();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					throw new BuildException(e.getMessage());
				}
			}
		}
		/*
		 * System.out.println("generateApplicationXML: " + applicationXml + ", "
		 * + jarFile + ", " + ejbClassSet.size());
		 */
		// 产生application.xml用于ear打包
		generateApplicationXML(applicationXml, jarFile,
				(ejbClassSet.size() > 0));
	}

	/**
	 * 建立依赖关系
	 * 
	 * @throws BuildException
	 */
	private void Maintenance() throws BuildException {
		// 确保找到至少一个文件集
		if (filesets.size() == 0)
			throw new BuildException("NO FILESET!");

		// 从clsLibs去除所有VALUE == libraryName的入口,以便重建
		refreshClassMappingLibrary(libraryName);

		for (int i = 0; i < filesets.size(); i++) {
			FileSet fs = filesets.get(i);
			DirectoryScanner ds = fs.getDirectoryScanner();
			String[] files = ds.getIncludedFiles();
			for (int j = 0; j < files.length; j++) {
				// System.out.println(fs.getDir());
				// System.out.println(files[j]);

				String clsname = files[j];
				// 不处理非.class文件
				if (!clsname.endsWith(".class"))
					continue;

				// 解析.class类文件
				Dependency dependency = null;
				try {
					dependency = Dependency.getDependency(fs.getDir()
							+ File.separator + files[j], clsPrefixName);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					throw new BuildException("ANALYZ class: " + fs.getDir()
							+ File.separator + files[j] + " FAILED!!!");
				}

				// 获取该class文件的全类名
				clsname = dependency.getSelfName();

				// 如果是entity
				if (dependency.isEntity()) {
					// 如果有primary key,则亦将其加入之
					/*
					 * if (dependency.hasPrimaryKey()){ if
					 * (!entityClassSet.contains
					 * (dependency.getPrimaryKeyClass()))
					 * entityClassSet.add(dependency.getPrimaryKeyClass()); }
					 */
					if (!entityClassSet.contains(clsname))
						entityClassSet.add(clsname);
				}

				// 如果是ejb
				if (dependency.isEJB() && !ejbClassSet.containsKey(clsname)) {
					ejbClassSet.put(clsname, !dependency.isMessageDrivenEJB());
				}

				// 将类名从依赖表中去除
				if (clsDepends.containsKey(clsname)) {
					clsDepends.remove(clsname);
				}

				// 从类-库依赖表中去除
				if (!clsLibs.containsKey(clsname)) {
					// 不包含该类,直接增加
					clsLibs.put(clsname, libraryName);
				} else if (!clsLibs.get(clsname).equals(libraryName)) {
					// 包含，但指向的库名不对,则先删除后增加
					clsLibs.remove(clsname);
					clsLibs.put(clsname, libraryName);
				}

				// 获取依赖集合
				HashSet<String> depends = dependency.getDependClass();
				if (depends == null || depends.size() == 0)
					depends = null;

				// 加入到类-依赖集合中
				clsDepends.put(clsname, depends);
			}
		}

		// 产生必要的xml文件
		generateAllXml();
	}

	public void putDependsToFile() {
		File sfn = new File(serialFileName);
		try {
			ObjectOutputStream oos = new ObjectOutputStream(
					new FileOutputStream(sfn, false));
			// 写MAGIC
			oos.writeInt(DEPENDS_MAGIC);

			// 写类依赖其他类的关系
			oos.writeObject(clsDepends);

			// 写类依赖LIB的关系
			oos.writeObject(clsLibs);

			oos.close();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new BuildException(e.getMessage());
		}
	}

	@SuppressWarnings("unchecked")
	public void getDependsFromFile() {
		File sfn = new File(serialFileName);
		if (sfn.exists()) {
			try {
				ObjectInputStream ois = new ObjectInputStream(
						new FileInputStream(sfn));
				int magic = ois.readInt();
				if (magic != DEPENDS_MAGIC)
					throw new BuildException("DEPENDS FILE ["
							+ sfn.getAbsolutePath() + "] MAGIC IS INVALID!");

				// 读类依赖其他类的关系
				clsDepends = (HashMap<String, HashSet<String>>) ois
						.readObject();

				// 读类依赖LIB的关系
				clsLibs = (HashMap<String, String>) ois.readObject();

				ois.close();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				throw new BuildException(e.getMessage());
			}
		} else {
			try {
				sfn.createNewFile();
				clsDepends = new HashMap<String, HashSet<String>>();
				clsLibs = new HashMap<String, String>();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				throw new BuildException(e.getMessage());
			}
		}
	}

	public void execute() throws BuildException {
		if (dependsCmd == null || dependsCmd.length() == 0)
			throw new BuildException("dependsCmd not Specified!");
		if (serialFileName == null || serialFileName.length() == 0)
			throw new BuildException("serialFileName not Specified!");
		// 从文件中重建对象
		getDependsFromFile();
		if (dependsCmd.equals(DEPENDS_CMD_MAINTENCE)) {
			// 建立对应关系
			Maintenance();
			// 写回到文件中
			putDependsToFile();
		} else if (dependsCmd.equals(DEPENDS_CMD_SHOW))
			Show();
		else if (dependsCmd.equals(DEPENDS_CMD_RESOLVE))
			Resolve();
		else
			throw new BuildException("dependsCmd ERROR!");
	}
}